/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aprendizajePorRefuerzo.agente;

import aprendizajePorRefuerzo.accion.Accion;
import aprendizajePorRefuerzo.estado.Estado;
import aprendizajePorRefuerzo.reward.Reward;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Fernando Sorzana
 */
public class AgenteSarsaLambda extends AgenteImp {
    
    private double lambda;
    
    private boolean bandera = false;
    
    private List<Estado> estadosPosibles = new ArrayList<Estado>();
    
    private Map<Estado,Map<Accion,Double>> matrizE = new HashMap<>();

    public double getLambda() {
        return lambda;
    }

    public void setLambda(double lambda) {
        this.lambda = lambda;
    }

    public List<Estado> getEstadosPosibles() {
        return estadosPosibles;
    }

    public void setEstadosPosibles(List<Estado> estadosPosibles) {
        this.estadosPosibles = estadosPosibles;
    }

    public Map<Estado, Map<Accion, Double>> getMatrizE() {
        return matrizE;
    }

    public void setMatrizE(Map<Estado, Map<Accion, Double>> matrizE) {
        this.matrizE = matrizE;
    }

    public void setValor(Estado estado, Accion accion, double valor) {
        if (!matrizE.containsKey(estado)){
            matrizE.put(estado, new HashMap<Accion,Double>());
        }
        matrizE.get(estado).put(accion, valor);
    }

    public double getValor(Estado estado, Accion accion) {
        if (matrizE.get(estado) == null || matrizE.get(estado).get(accion) == null){
            return 0.0;
        } else {
            return matrizE.get(estado).get(accion);
        }
    }

    private Accion nuevaAccion;

    public Accion getNuevaAccion() {
        return nuevaAccion;
    }

    public void setNuevaAccion(Accion nuevaAccion) {
        this.nuevaAccion = nuevaAccion;
    }

    @Override
    public void aprender(Estado estado, Reward reward) {
        setAccionAnterior(nuevaAccion);
        nuevaAccion = getPolitica().tomarAccion(estado, getFuncionQ(), getAccionesPosibles());
        double qAnterior = getFuncionQ().getValor(getEstadoAnterior(), getAccionAnterior());
        double qNueva = getFuncionQ().getValor(estado, nuevaAccion);
        double delta = reward.getValor() + getGamma() * qNueva - qAnterior;
        getFuncionQ().setValor(getEstadoAnterior(), getAccionAnterior(), qAnterior + getAlfa() * (reward.getValor() + getGamma() * qNueva - qAnterior));
        if (!bandera){
            matrizE.put(getEstadoAnterior(), new HashMap<Accion,Double>());
            matrizE.get(getEstadoAnterior()).put(getAccionAnterior(), 0.0);
        }
        matrizE.get(getEstadoAnterior()).put(getAccionAnterior(),matrizE.get(getEstadoAnterior()).get(getAccionAnterior()) + 1);
        for (Estado e: getEstadosPosibles()){
            if (!bandera){
                matrizE.put(e, new HashMap<Accion,Double>());
            }
            for (Accion a : getAccionesPosibles()){
                if (!bandera){
                    matrizE.get(e).put(a, 0.0);
                }
                getFuncionQ().setValor(e, a, getFuncionQ().getValor(e, a) + getAlfa() * delta * matrizE.get(e).get(a));
                matrizE.get(e).put(a,getGamma() * delta * matrizE.get(e).get(a));
            }
        }
        bandera = true;
    }

    @Override
    public Accion tomarAccion(Estado estado) {
        if (nuevaAccion == null){
            return super.tomarAccion(estado);
        } else {
            setEstadoAnterior(estado);
            //setAccionAnterior(getPolitica().tomarAccion(estado, getFuncionQ(), getAccionesPosibles()));
            return nuevaAccion;
        }
    }

    @Override
    public String toString() {
        return "Agente Sarsa-Lambda";
    }
    
    
    
}
